/* 
 * File:   MoKnetG.h
 * Author: CreMindES
 *
 * Created on 2012. szeptember 16., 10:21
 */

#ifndef MOKNETG_H
#define	MOKNETG_H


#define _XTAL_FREQ                          16000000
// TODO: calculate normal value!!
#define RTU_DELAY                           256-_XTAL_FREQ/256/256/4

#define USART1_RX_LED_ON()                  LATD0 = 1
#define USART1_RX_LED_OFF()                 LATD0 = 0
#define USART1_TX_LED_ON()                  LATD1 = 1
#define USART1_TX_LED_OFF()                 LATD1 = 0
#define USART2_RX_LED_ON()                  LATD2 = 1
#define USART2_RX_LED_OFF()                 LATD2 = 0
#define USART2_TX_LED_ON()                  LATD3 = 1
#define USART2_TX_LED_OFF()                 LATD3 = 0

#define DISABLE_USART1_RECEPTION()          PIE1bits.RC1IE = 0
#define ENABLE_USART1_RECEPTION()           PIE1bits.RC1IE = 1
#define DISABLE_USART2_RECEPTION()          PIE3bits.RC2IE = 0
#define ENABLE_USART2_RECEPTION()           PIE3bits.RC2IE = 1

// Prototypes

// Device specific functions
void initDevice(void);
void readConfiguration(void);
void initTimer0(void);
void initTimer1(void);
//void initTimer2(void);
void turnLEDsOff(void);
void resetDeviceArray(void);

void interrupt myISR(void);

void startTimeoutCheckService(void);        // TODO: finish implementing
void stopTimeoutCheckService(void);
void resetCommunication(void);

// USART 1 functions
void initUsart1(void);
void switchUsart1ToTx(void);
void switchUsart1ToRx(void);
void receiveAsciiMessage(void);
void sendUsart1Data(void);

// USART 2 functions
void initUsart2(void);
void switchUsart2ToTx(void);
void switchUsart2ToRx(void);
void receiveRtuMessage(void);
void sendUsart2Data(void);

void waitForNextRtuCharacter(void);

unsigned char validateAsciiMessage(void);
unsigned char validateRtuMessage(void);

// LRC, CRC
unsigned char generateLRC(unsigned char len, unsigned char *buffer);
unsigned int generateCRC(unsigned char len, unsigned char *buffer);

// Converter functions
unsigned char convertAsciiMessageToRtu(void);
unsigned char convertRtuMessageToAscii(void);

unsigned char convertAsciiToRtu(unsigned char *asciiBuffer, unsigned char byteNumber);
unsigned char convertRtuToAscii(unsigned char *rtuBuffer, unsigned char byteNumber);

unsigned char convertHexToAsciiHi(unsigned char num);
unsigned char convertHexToAsciiLo(unsigned char num);

char convertDecToHexInAsciiHi(int num);
char convertDecToHexInAsciiLo(int num);


enum communicationStates {
    idle,                   // 0
    receivingAsciiMessage,  // 1
    receivingRtuMessage,    // 2
    convertingDataFormat,   // 3
    sendingMessage,         // 4
    error                   // 5
};

enum messageAvailabilityOptions {
    noMessageIsAvailable,       // 0
    asciiMessageIsAvailable,    // 1
    rtuMessageIsAvailable       // 2
};

/*
enum rtuMessageStatusOptions {
    rtuIdle,
    receivingRtuMessage,
    rtuMessageReceived
};
*/

enum errosStates {
    noError,                // 0
    invalidAsciiMessage,    // 1
    invalidRtuMessage,      // 2
    unknownError            // 3
};

enum usartxTransmissionModes {
    ASCII_MODE,             // 0
    RTU_MODE                // 1
};

enum txBufferStatusOptions {
    txEmpty,
    txAsciiMessageAvailable,
    txRtuMessageAvailable
};

/*
enum trasnmissionState {
    IDLE_STATE,             // 0
    RECEIVING_STATE,        // 1
    ERROR_STATE             // 2
};
*/

unsigned char usart1BaudRateTemp = 0;
unsigned char usart2BaudRateTemp = 0;

enum usartxBaudRateOptions {
    B_2400  = (_XTAL_FREQ/64/2400)-1,
    B_9600  = (_XTAL_FREQ/64/9600)-1,
    B_19200 = (_XTAL_FREQ/64/19200)-1,
    B_38400 = (_XTAL_FREQ/64/38400)-1
};

enum usartxMasterOptions {
    NO_MASTER,
    USART1_MASTER,
    USART2_MASTER
};

/*
// Variables
enum messageParts {
    DEVICE_ADDRESS,         // 0
    FUNCTION,               // 1
    REGISTER_ADDRESS,       // 2
    DATA_COUNT,             // 3
    IS_DATA_FLOAT,          // 4
    DATA_VALUE_INT,         // 5
    MESSAGE_PART_NUM        // 6
};

enum eKnetRegisterType {
    UNIVERSAL_INPUT,        // 0
    DIGITAL_INPUT,          // 1
    ANALOG_OUTPUT,          // 2
    RELAY_OUTPUT,           // 3
    NUMERIC,                // 4
                            // there is no 5
    TIMER = 6,              // 6
    SYSTEM_VARIABLE = 7     // 7
};

enum eExceptionResponse {
    ILLIGAL_FUNCTION = 1,   // 1
    ILLIGAL_DATA_ADDRESS,   // 2
    ILLIGAL_DATA_VALUE,     // 3
    SLAVE_DEVICE_FAILURE,   // 4
    ACKNOWLEDGE,            // 5
    SLAVE_DEVICE_BUSY,      // 6
    NEGATIVE_ACKNOWLEDGE,   // 7
    MEMORY_PARITY_ERROR     // 8
};
*/

static const char hexChars[] = "0123456789ABCDEF";

//unsigned char transmissionState = IDLE_STATE;
unsigned char communicationState = idle;
unsigned char messageAvailability = noMessageIsAvailable;
unsigned char errorState = noError;
unsigned char txBufferState = txEmpty;

//unsigned char rtuMessageStatus = rtuIdle;

// TODO make a struct for USART1 and USART2 each.
unsigned char usart1BaudRate = B_9600;
unsigned char usart2BaudRate = B_9600;
unsigned char usart1TransmissionMode = ASCII_MODE;
unsigned char usart2TransmissionMode = ASCII_MODE;
unsigned char usartxMaster = NO_MASTER;

// USART1
unsigned char usart1RxBuffer[150];
unsigned char usart1TxBuffer[150];
unsigned char usart1RxCount = 0;
unsigned char usart1TxCount = 0;

// USART2
unsigned char usart2RxBuffer[150];
unsigned char usart2TxBuffer[150];
unsigned char usart2RxCount = 0;
unsigned char usart2TxCount = 0;

// ASCII Side
unsigned char *asciiRxBuffer =  usart1RxBuffer;
unsigned char *asciiRxCount  = &usart1RxCount;
unsigned char *asciiTxBuffer =  usart1TxBuffer;
unsigned char *asciiTxCount  = &usart1TxCount;

// RTU Side
unsigned char *rtuRxBuffer   =  usart2RxBuffer;
unsigned char *rtuRxCount    = &usart2RxCount;
unsigned char *rtuTxBuffer   =  usart2TxBuffer;
unsigned char *rtuTxCount    = &usart2TxCount;

int messageAddress, messageFunction, messageDataAddress, messageDataType;
int messageDataCount, messageDataNumber, messageDataValueInt;
float messageDataValueFloat;

//unsigned int timeoutCount = 0;

#endif	/* MOKNETG_H */



